package com.hup.minicontroller.server.service;

import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;

import androidx.annotation.NonNull;

import com.hup.minicontroller.common.framework.MainThreadHandler;
import com.hup.minicontroller.server.R;
import com.hup.minicontroller.server.ServerApplication;
import com.hup.minicontroller.server.auth.FloaterAuthForCFS;
import com.hup.minicontroller.server.model.ControlConfig;
import com.hup.minicontroller.server.mvp.ICursorFloaterView;
import com.hup.minicontroller.server.mvp.IMainView;

import java.util.function.Supplier;

/**
 * 光标悬浮窗服务:展示触摸事件的光标<pre>
 * 权限: {@link FloaterAuthForCFS}
 */
public class CursorFloaterService implements ICursorFloaterView {
    private static final String TAG = CursorFloaterService.class.getSimpleName();
    private final MyHandler myHandler;

    private WindowManager windowManager;
    private ImageView ivCursor;
    private int[] parentViewLocation = new int[2];

    private ControlConfig controlConfig;

    public CursorFloaterService() {
        Log.i(TAG, "onCreate: ");
        controlConfig = ServerApplication.getBean(MainService.class).getAppState().getControlConfig();
        myHandler = new MyHandler(() -> ivCursor);
        if (controlConfig.isShowCursor()) {
            //触发初始化悬浮窗,因为此时还在Application.onCreate中,所以需要delay等待Activity启动
            ServerApplication.getBean(MainThreadHandler.class).postDelayed(this::onUpdateShowCursor, 500);
        }
    }

    private void initFloaterView() {
        Context context = ServerApplication.getContext();
        windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
        mParams.height = WindowManager.LayoutParams.MATCH_PARENT;
        mParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        mParams.format = PixelFormat.TRANSLUCENT;
        mParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;

//        mParams.type = LayoutParams.TYPE_SYSTEM_ERROR;//能覆盖状态栏,6.0(版本号不确定)前的做法,10.0提示无权限
        if (!MainService.IS_SYSTEM_APP) {
            mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;//不能覆盖状态栏
        } else {
            //看注释,应该能覆盖状态栏,但需要是系统应用,否则permission denied
            mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;//
            mParams.type = LayoutParams.TYPE_SYSTEM_OVERLAY;
        }

        //要设为?? 否则mParams的中点不是左上角
        mParams.gravity = Gravity.TOP + Gravity.START;

        ViewGroup floaterRoot = (ViewGroup) View.inflate(context, R.layout.cursor_floater, null);
        ivCursor = floaterRoot.findViewById(R.id.iv_cursor);

        windowManager.addView(floaterRoot, mParams);
        //floaterRoot.setDrawingCacheEnabled(true);
    }

    @Override
    public void doTerminate() {
        Log.i(TAG, "doTerminate: ");
        ServerApplication.removeBean(ICursorFloaterView.class);
        if (windowManager != null) {
            windowManager.removeView((View) ivCursor.getParent());
            windowManager = null;
            ivCursor = null;
        }
    }

    @Override
    public void onUpdateShowCursor() {
        if (!controlConfig.isShowCursor()) {
            ivCursor.setVisibility(View.INVISIBLE);
            myHandler.removeMessages(MyHandler.HIDE_CURSOR);
            return;
        }
        if (windowManager != null) {
            //悬浮窗已初始化
            flashCursor();
            return;
        }
        //显示光标,但悬浮窗未初始化
        try {
            if (!FloaterAuthForCFS.hasAuth()) {
                IMainView mainView = ServerApplication.getBeanNullable(IMainView.class);
                if (mainView == null) {
                    Log.e(TAG, "onUpdateShowCursor: 没有启动Activity?");//不会发发生的
                    return;
                }
                //申请权限,在acquireFloaterAuthResult处理结果
                FloaterAuthForCFS.acquireFloaterAuthForService((Activity) mainView);
                return;
            }
            Log.i(TAG, "onUpdateShowCursor: 正在启动悬浮窗");
            initFloaterView();
            flashCursor();
        } catch (Exception e) {
            Log.e(TAG, "onUpdateShowCursor: 悬浮窗初始化异常:" + e);
            windowManager = null;
            ivCursor = null;
            controlConfig.setShowCursor(false);
            ServerApplication.executeIfExist(IMainView.class, IMainView::onControlConfigChanged);
        }
    }

    @Override
    public void acquireFloaterAuthResult() {
        if (!FloaterAuthForCFS.hasAuth()) {
            Log.i(TAG, "acquireFloaterAuthResult: 无悬浮窗权限");
            controlConfig.setShowCursor(false);
            ServerApplication.executeIfExist(IMainView.class, IMainView::onControlConfigChanged);
            return;
        }
        onUpdateShowCursor();
    }

    /**
     * 显示光标,n秒后隐藏光标;
     * 用于连接成功时让光标"闪一下"
     */
    private void flashCursor() {
        ivCursor.setVisibility(View.VISIBLE);
        myHandler.sendEmptyMessageDelayed(MyHandler.HIDE_CURSOR, MyHandler.CURSOR_HIDE_TIME);
    }

    @Override
    public void onClientOnline() {
        if (ivCursor != null) {
            ivCursor.setVisibility(View.GONE);//如果已经是VISIBLE,则flashCursor是不会触发屏幕图像更新的
            myHandler.removeMessages(MyHandler.HIDE_CURSOR);
            flashCursor();
        }
    }

    @Override
    public void onFullScreenTouch(int action, int x, int y) {
        if (!MainService.IS_SYSTEM_APP) {
            //不是系统app时,parent不覆盖整个屏幕,需要减去"左,上"的像素
            View parent = (View) ivCursor.getParent();
            parent.getLocationOnScreen(parentViewLocation);
//            Log.i(TAG, "onFullScreenTouch: parentViewLocation=" + Arrays.toString(parentViewLocation));
            x -= parentViewLocation[0];
            y -= parentViewLocation[1];
        }
        ivCursor.setX(x);
        ivCursor.setY(y);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                ivCursor.setImageResource(R.drawable.cursor_pressed);
                myHandler.removeMessages(MyHandler.HIDE_CURSOR);
                ivCursor.setVisibility(View.VISIBLE);
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                ivCursor.setImageResource(R.drawable.cursor);
                myHandler.sendEmptyMessageDelayed(MyHandler.HIDE_CURSOR, MyHandler.CURSOR_HIDE_TIME);
                break;
        }
    }

    @Override
    public void onTouchPadMoveStart(int[] cursorParentLocationOnScreen, int[] cursorLocationOnScreen) {
        ((View) ivCursor.getParent()).getLocationOnScreen(cursorParentLocationOnScreen);
        ivCursor.getLocationOnScreen(cursorLocationOnScreen);
        myHandler.removeMessages(MyHandler.HIDE_CURSOR);
        ivCursor.setVisibility(View.VISIBLE);
    }

    @Override
    public void onTouchPadMove(int cursorXOnParent, int cursorYOnParent) {
        ivCursor.setX(cursorXOnParent);
        ivCursor.setY(cursorYOnParent);
    }

    @Override
    public void onTouchPadMoveStop() {
        myHandler.sendEmptyMessageDelayed(MyHandler.HIDE_CURSOR, MyHandler.CURSOR_HIDE_TIME);
    }

    @Override
    public void onTouchPadPress(int[] cursorLocationOnScreen) {
        ivCursor.getLocationOnScreen(cursorLocationOnScreen);
        myHandler.removeMessages(MyHandler.HIDE_CURSOR);
        ivCursor.setImageResource(R.drawable.cursor_pressed);
        ivCursor.setVisibility(View.VISIBLE);
    }

    @Override
    public void onTouchPadUp(int[] cursorLocationOnScreen) {
        ivCursor.getLocationOnScreen(cursorLocationOnScreen);
        ivCursor.setImageResource(R.drawable.cursor);
        myHandler.sendEmptyMessageDelayed(MyHandler.HIDE_CURSOR, MyHandler.CURSOR_HIDE_TIME);
    }

    @Override
    public void onTouchPadClick(int[] cursorLocationOnScreen) {
        ivCursor.getLocationOnScreen(cursorLocationOnScreen);
        myHandler.removeMessages(MyHandler.HIDE_CURSOR);
        ivCursor.setImageResource(R.drawable.cursor_pressed);
        ivCursor.setVisibility(View.VISIBLE);
        ivCursor.postDelayed(() -> ivCursor.setImageResource(R.drawable.cursor), 100);
        myHandler.sendEmptyMessageDelayed(MyHandler.HIDE_CURSOR, MyHandler.CURSOR_HIDE_TIME);
    }

    private static class MyHandler extends Handler {
        /**
         * 光标自动隐藏的间隔
         */
        private static final int CURSOR_HIDE_TIME = 5000;
        private static final int HIDE_CURSOR = 1;
        private final Supplier<View> cursorViewSupplier;

        /**
         * @param cursorViewSupplier 由于是静态类(as警告非静态类会内存溢出),而view又不是一开始就得到实例的,所以用Supplier
         */
        public MyHandler(Supplier<View> cursorViewSupplier) {
            super(Looper.getMainLooper());
            this.cursorViewSupplier = cursorViewSupplier;
        }

        @Override
        public void handleMessage(@NonNull Message msg) {
            if (msg.what == HIDE_CURSOR) cursorViewSupplier.get().setVisibility(View.INVISIBLE);
        }
    }

}
